package cn.kai.basic.interceptor;

import cn.kai.basic.anno.PreAuthorize;
import cn.kai.basic.jwt.JwtUtils;
import cn.kai.basic.jwt.Payload;
import cn.kai.basic.jwt.RsaUtils;
import cn.kai.basic.jwt.UserInfo;
import cn.kai.system.mapper.PermissionMapper;
import cn.kai.user.domain.Logininfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.security.Key;
import java.security.Permission;
import java.security.PublicKey;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class LogionInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PermissionMapper permissionMapper;

    @Value("${jwt.rsa.pub}")
    private String jwtRsaPublic; // 通过yml配置文件获取公钥

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("4444444444");
        //1.非空判断
        //2.取出token
        String token = request.getHeader("token");
        //设置字符编码集
        response.setCharacterEncoding("UTF-8");
        //设置响应参数为JSON
        response.setContentType("application/json,charset=UTF-8");
        if (!StringUtils.isBlank(token)){
            //3.用token去Redis中取logininfo对象,对象存在放行
            //改造一：解析token，就是解析jwt字符串
            PublicKey publicKey = RsaUtils.getPublicKey(JwtUtils.class.getClassLoader().getResource(jwtRsaPublic).getFile());
            Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token, publicKey, UserInfo.class);
            if(payload != null){
                UserInfo userInfo = payload.getUserInfo();
                Logininfo logininfoTmp = new Logininfo();
            //改造二：从JWT解密出来的对象中获取logininfo对象
                BeanUtils.copyProperties(userInfo.getLogininfo(),logininfoTmp);
                if (logininfoTmp.getType() == 0) {
                    // 进入到此判断说明是员工，那么获取到用户访问接口我们自定义的@PreAuthorize注解的sn值，用来确定用户访问的是那个URL权限
                    // 得到本次请求的方法对象
//                    if(!HandlerMethod.class.equals(handler.getClass())){
//                        PrintWriter writer = response.getWriter();
//                        writer.write("{\"success\":false,\"resultObj\":\"调用接口错误！\"}");
//                        writer.flush();
//                        writer.close();
//                        return false;
//                    }
                    HandlerMethod handlerMethod = (HandlerMethod) handler;
                    // 从方法对象中的到指定注解
                    PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
                    // 判断方法上是否有此注解，如果没有说明是公共资源
                    if (preAuthorize != null) {
                        // 从注解中获取到sn值，也就是本次请求对应的权限编码，用于判断用户是否有此URL权限
                        String permissionSn = preAuthorize.sn();
                        // 获取到用户所拥有的所有权限
                        // List<String> ownPermissions = permissionMapper.loadOwnPermissionByLogininId(logininfoTmp.getId());
                        // 改造三：直接从JWT解析出来的对象中获取用户权限集合
                        if (!userInfo.getPermissions().contains(permissionSn)) {
                            // 员工所有的权限不包含访问的权限，那么直接设置响应信息并拦截
                            PrintWriter writer = response.getWriter();
                            writer.write("{\"success\":false,\"resultObj\":\"noLogin\"}");
                            writer.flush();
                            writer.close();
                            return false;
                        }
                    }
                    return true;
                }else if (logininfoTmp.getType() == 1){
                    return true;
                }
            }
//            Logininfo logininfo = (Logininfo) redisTemplate.opsForValue().get(token);
//            if(logininfo != null){
//                //获取当前请求方法
//                HandlerMethod method = (HandlerMethod) handler;
//                PreAuthorize annotation = method.getMethodAnnotation(PreAuthorize.class);
//                if (null != annotation){
//                    String sn = annotation.sn();
//                    //获取用户所拥有的所有权限
//                    List<String> snList =  permissionMapper.findByLogininfoId(logininfo.getId());
//                    if(!snList.contains(sn)){ // 不在权限列表中
//                        //4.不存在拦截 并要返回 {"success":false,"resultObj":"nologin"}
//                        //获取打印流，并响应数据
//                        PrintWriter writer = response.getWriter();
//                        writer.write("{\"success\":false,\"resultObj\":\"noPermission\"}");
//                        //关流
//                        writer.flush();
//                        writer.close();
//                        return false;
//                    }
//                }
////                重置Redis的过期时间
//                redisTemplate.expire(token,30, TimeUnit.MINUTES);
//                return true;
//            }
        }
        PrintWriter writer = response.getWriter();
        writer.write("{\"success\":false,\"resultObj\":\"noLogin\"}");
        //关流
        writer.flush();
        writer.close();
        return false;
    }
}
